export default class SocketService {
  /**
   * 单例模式
   */
  static instance = null

  static get Instance() {
    if (!this.instance) {
      this.instance = new SocketService()
    }
    return this.instance
  }

  // WebSocket连接对象
  ws = null

  // 记录是否连接成功
  isConnect = false

  // 记录重试发送数据次数
  retryCount = 0

  // 记录重新连接次数
  connectCount = 0
  // 存储回调函数
  callBackMapping = {}

  /**
   * 用于连接操作socket
   */
  connect() {
    if (!window.WebSocket) {
      return console.error('你的浏览器不支持连接webSocket')
    }
    this.ws = new WebSocket('ws://localhost:9989')
    this.ws.onopen = () => {
      console.log('webSocket连接成功')
      this.isConnect = true
      this.connectCount = 0
    }
    this.ws.onclose = () => {
      console.log('webSocket连接失败')
      this.isConnect = false
      this.connectCount++
      setTimeout(() => {
        this.connect()
      }, this.connectCount * 500)
    }
    this.ws.onmessage = msg => {
      // 最终的需要使用到的数据在 JSON.parse(msg.data).data
      let res = null
      if (typeof msg.data === 'string') {
        res = JSON.parse(msg.data)
      } else {
        res = msg.data
      }
      const { socketType, action } = res
      // 判断对应类型的回调函数是否存在
      if (this.callBackMapping[socketType]) {
        if (action === 'getData') {
          const realData = JSON.parse(res.data)
          this.callBackMapping[socketType].call(this, realData)
        } else if (action === 'fullScreen') {
          this.callBackMapping[socketType].call(this, res)
        } else if (action === 'themeChange') {
          this.callBackMapping[socketType].call(this, res)
        }
      }
    }
  }

  // 回调函数的注册
  registerCallBack(socketType, callBack) {
    this.callBackMapping[socketType] = callBack
  }

  // 取消某一个回调函数
  unRegisterCallBack(socketType) {
    this.callBackMapping[socketType] = null
  }
  // 发送数据的方法
  send(data) {
    // 判断此时此刻有没有连接成功
    if (this.isConnect) {
      this.ws.send(JSON.stringify(data))
      this.retryCount = 0
    } else {
      this.retryCount++
      // 延时重新发送数据
      setTimeout(() => {
        this.send(data)
      }, this.retryCount * 500)
    }
  }
}
